/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Parsing des requêtes IRC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Auteur: Thaeron
Projet: NewSyndrome
Licence: GPL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

#include "NewSyndrome.h"
#define MALLOCS_BLOC 10

static void identify (msg * irc, char *buffer);
static int parse_argu (msg * irc, char *buffer, const char *ref_txt);


static int parse_argu (msg * irc, char *buffer, const char *ref_txt)
{
	char *runner = buffer;
	char *buffer_start = buffer;
	unsigned int cc = 0;
	int do_not_inc, nb_allocs = MALLOCS_BLOC;
  
	irc->argu = NULL;
	irc->raw_tab = NULL;
	
	while (*buffer != '\0')
	{
		for (do_not_inc = 0; *buffer != ' ' && *buffer; buffer++);
		if (!(*buffer))
			do_not_inc = 1;
		else
			*buffer = '\0';
      
		if (nb_allocs == MALLOCS_BLOC)
		{
			irc->argu = (char **) realloc (irc->argu, (cc + MALLOCS_BLOC) * sizeof (char *));
			if (ref_txt)
				irc->raw_tab = (char **) realloc (irc->raw_tab, (cc + MALLOCS_BLOC) * sizeof (char *));
			nb_allocs = 0;
		}
		irc->argu[cc] = runner;
		if (ref_txt)
			irc->raw_tab[cc] = (runner - buffer_start) + (char *) ref_txt;
		cc++;
		nb_allocs++;
      
		if (!do_not_inc)
			buffer++;
		while (*buffer == ' ')
			buffer++;
      
		runner = buffer;
	}
	irc->argu = (char **) realloc (irc->argu, cc * sizeof (char *));
	if (ref_txt)
		irc->raw_tab = (char **) realloc (irc->raw_tab, cc * sizeof (char *));
	
	return (cc);
}


static void identify (msg * irc, char *buffer)
{
	char *br;
	unsigned int n;

	for (br = buffer; *br != '!' && *br; br++);
	n = br - buffer;
	irc->sender_nick = (char *) malloc (n + 1);
	strncpy (irc->sender_nick, buffer, n);
	*(irc->sender_nick + n) = '\0';
	if (!(*br))
		return;

	for (buffer = ++br; *br != '@' && *br; br++);
	n = br - buffer;
	irc->sender_ident = (char *) malloc (n + 1);
	strncpy (irc->sender_ident, buffer, n);
	*(irc->sender_ident + n) = '\0';
	if (!(*br))
		return;

	irc->sender_host = (char *) malloc (strlen (++br) + 1);
	strcpy (irc->sender_host, br);
}


void free_msg (msg *irc)
{
	if (irc->argu_backend)
		free (irc->argu_backend);
	if (irc->argu)
		free (irc->argu);
	if (irc->raw_tab)
		free (irc->raw_tab);
	if (irc->cmd != NULL)
		free (irc->cmd);
	if (irc->dest != NULL)
		free (irc->dest);
	if (irc->sender != NULL)
		free (irc->sender);
	if (irc->sender_nick != NULL)
		free (irc->sender_nick);
	if (irc->sender_ident != NULL)
		free (irc->sender_ident);
	if (irc->sender_host != NULL)
		free (irc->sender_host);
}


int parse_buffer (msg * irc, char *runner)
{
	int ct;
	byte point, youp;
	char *plot;

	irc->raw_txt = NULL;
	irc->raw_tab = NULL;

	if (*runner == ':')
	{
		for (youp = 0, plot = runner, runner++;  *runner != 0 && youp < 3; runner++)
		if (*runner == ' ')
			youp++;

		if (*runner == ':')
			*runner++ = '\0';
		else if (*runner)
			*(runner - 1) = '\0';

		irc->sender_nick = NULL;
		irc->sender_ident = NULL;
		irc->sender_host = NULL;
		irc->cmd = NULL;
		irc->dest = NULL;
		irc->sender = NULL;

		irc->argu_backend = strdup (++plot);
		ct = parse_argu (irc, irc->argu_backend, NULL);		/* header */

		if (ct > 0)
		{
			irc->sender = (char *) malloc (strlen (irc->argu[0]) + 1);
			strcpy (irc->sender, irc->argu[0]);

			identify (irc, irc->sender);
		}
		else
		{
			irc->sender = (char *) malloc (1);
			*irc->sender = '\0';
		}
		if (ct > 1)
		{
			irc->cmd = (char *) malloc (strlen (irc->argu[1]) + 1);
			strcpy (irc->cmd, irc->argu[1]);
		}
		else
		{
			irc->cmd = (char *) malloc (1);
			*irc->cmd = '\0';
		}
		if (ct > 2)
		{
			irc->dest = (char *) malloc (strlen (irc->argu[2]) + 1);
			if (*irc->argu[2] == ':')
			{
				if (!strcasecmp (irc->cmd, "QUIT"))
				{
					*(runner - 1) = ' ';
					runner -= strlen (irc->argu[2]);
					free (irc->dest);
					irc->dest = (char *) malloc (1);
					*irc->dest = '\0';
				}
				else
					strcpy (irc->dest, (irc->argu[2] + 1));
			}
			else
				strcpy (irc->dest, irc->argu[2]);
		}
		else
		{
			irc->dest = (char *) malloc (1);
			*irc->dest = '\0';
		}
		free (irc->argu_backend);
		free (irc->argu);

		/* ici le pointeur de texte */
		irc->argu_backend = strdup (runner);
		ct = parse_argu (irc, irc->argu_backend, runner);	/* texte */
		irc->raw_txt = runner;
		irc->nbarg = ct;
      
		if (irc->cmd)
			return (1);
		
		return (0);
	}
	else
	{
		for (plot = runner, runner++; *runner != ':' && *runner; runner++);
		if (*runner == ':')
			point = 1;
		else
			point = 0;

		*runner++ = '\0';

		irc->argu_backend = strdup (plot);
		ct = parse_argu (irc, irc->argu_backend, NULL);

		irc->cmd = NULL;

		if (ct >= 1)
		{
			irc->cmd = (char *) malloc (strlen (irc->argu[0]) + 1);
			strcpy (irc->cmd, irc->argu[0]);
		}
		free (irc->argu_backend);
		free (irc->argu);
				
		if (point)
		{
			/* pointeur de texte ici */
			irc->argu_backend = strdup (runner);
			ct = parse_argu (irc, irc->argu_backend, runner);
			irc->raw_txt = runner;
			irc->nbarg = ct;
		}
		else
		{
			irc->argu_backend = NULL;
			irc->argu = NULL;
			irc->nbarg = 0;
		}

		irc->sender_nick = (char *) malloc (1);
		*irc->sender_nick = '\0';
		irc->sender_host = (char *) malloc (1);
		*irc->sender_host = '\0';
		irc->sender_ident = (char *) malloc (1);
		*irc->sender_ident = '\0';
		irc->sender = (char *) malloc (1);
		*irc->sender = '\0';
		irc->dest = (char *) malloc (1);
		*irc->dest = '\0';


		if (irc->cmd != NULL)
			return (1);
		
		return (0);
	}
}
